#pragma once
#include <iostream>
#include <string>
#include "Connection.hpp"
#include "Log.hpp"
#include "protocol.hpp"
#include "Calculate.hpp"
using namespace std;

class HandlerEvent {
public :
    static void HandlerRequest(Connection* conn) {
        string& inbuffer = conn->Inbuffer();
        string message;
        Factory fact;
        auto req = fact.BuildRequest();
        while (Decode(inbuffer, &message)) {
            // 反序列化
            if (!req->DeSerialize(message)) {
                continue;
            }
            // 进行计算
            auto resp = Cal(req);

            // 对resp进行序列化
            string send_message = resp->Serialize();
            // 封装报文
            send_message = Encode(send_message);
            conn->AddOutbuffer(send_message);
        }
        // 发送
        if (!conn->OutbufferEmpty()) {
            conn->_sender(conn);
        }
        
    }

    // 我们在这里读取数据的时候，我们不关心数据的格式是怎样的，也不关心协议是怎样的。
    // 我们只负责吧本轮数据读完，交给上层去处理
    static void recver(Connection* conn) {
        // 直接读
        char buffer[1024];
        while (true) {
            ssize_t n = recv(conn->SockFd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0) {
                buffer[n] = '\0';
                conn->AddInbuffer(buffer);
            } else {
                if (errno == EAGAIN) {
                    // 说明本轮数据已经读完
                    break;
                } else if (errno == EINTR) {
                    // 说明被信号中断了
                    continue;
                } else {
                    lg.LogMessage(Warning, "write error, errno: %d, error string: %s", errno, strerror(errno));
                    conn->_excepter(conn); // 错误处理
                    return;
                }
            }
        }
        // 业务处理
        HandlerRequest(conn);

    }
    static void sender(Connection* conn) {
        string& outbuffer = conn->Outbuffer();
        // 直接发
        while (true) {
            ssize_t n = send(conn->SockFd(), outbuffer.c_str(), outbuffer.size(), 0);
            if (n >= 0) { 
                outbuffer.erase(0, n);
                if (conn->OutbufferEmpty()) {
                    break;
                }
            } else {
                if (errno == EAGAIN) {
                    break;
                } else if (errno == EINTR) {
                    continue;
                } else {
                    lg.LogMessage(Error, "sender error, errno: %d, error string: %s", errno, strerror(errno));
                    conn->_excepter(conn);
                    return;
                }
            }
        }


        // 只要走到循环后面，就说明我们本轮数据发满了，但是缓冲区中的数据可能还没有发完，
        // 所以需要开启对conn->SockFd() EPOLLOUT的关心
        if (!conn->OutbufferEmpty()) {
            // 开启对写事件的关心
            conn->_R->SetWriteRead(conn, true, true);
        } else {
            conn->_R->SetWriteRead(conn, true, false);
        }
    }
    static void excepter(Connection* conn) {
        conn->_R->DelConnection(conn);
    }

private :
};